package com.qyer.search.model.lastminute;

import static com.qyer.commons.utils.CommonUtils.cast2Int;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.qyer.search.cache.mutable.MutableCaches;
import com.qyer.search.filter.AbstractFilter;
import com.qyer.search.filter.AbstractValidator;
import com.qyer.search.model.Channel;
import com.qyer.search.model.SearchParameter;
import com.qyer.search.model.SearchParameterOrigin;
import org.apache.commons.collections4.MapUtils;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * User: Z J Wu Date: 2016/01/05 Time: 19:01 Package: com.qyer.search.model.lastminute
 */
@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.PUBLIC_ONLY)
@JsonIgnoreProperties(ignoreUnknown = true)
public class SimpleSKU extends SKU {

  @JsonProperty(FIELD_OUT_ID)
  private int id;
  @JsonIgnore
  private int type1;
  @JsonProperty(FIELD_OUT_TYPE2)
  private int type2;
  @JsonIgnore
  private long start_time;
  @JsonIgnore
  private long end_time;

  public SimpleSKU() {
  }

  public SimpleSKU(int id) {
    this.id = id;
  }

  private static SimpleSKU build(int id) {
    return new SimpleSKU(id);
  }

  public static SimpleSKU build(SearchParameter sp, Map<String, Object> dataMap) {
    if (MapUtils.isEmpty(dataMap)) {
      return null;
    }
    int id = cast2Int(dataMap.get(FIELD_ID));
    AbstractValidator validator = MutableCaches.getInstance().SKU_AVAILABILITY_VALIDATOR
      .getCacheContent();
    if (!validator.isValid(sp, id)) {
      return null;
    }
    return build(id).type1(cast2Int(dataMap.get(FIELD_TYPE1)))
                    .type2(cast2Int(dataMap.get(FIELD_TYPE2)));
  }

  public static SimpleSKU build(SearchParameterOrigin sp, Map<String, Object> dataMap) {
    if (MapUtils.isEmpty(dataMap)) {
      return null;
    }
    int id = cast2Int(dataMap.get(FIELD_ID));
    AbstractValidator validator = MutableCaches.getInstance().SKU_AVAILABILITY_VALIDATOR
      .getCacheContent();
    if (!validator.isValid(sp, id)) {
      return null;
    }
    return build(id).type1(cast2Int(dataMap.get(FIELD_TYPE1)))
                    .type2(cast2Int(dataMap.get(FIELD_TYPE2)));
  }

  public static SimpleSKU build(SearchParameterOrigin sp, Map<String, Object> dataMap,
                                Map<Integer,Map<Integer,Integer>> placeSearchCensus,
                                Map<Integer,Map<Integer,Integer>> typeSearchCensus) {
    if (MapUtils.isEmpty(dataMap)) {
      return null;
    }
    int id = cast2Int(dataMap.get(FIELD_ID));
    AbstractValidator validator = MutableCaches.getInstance().SKU_AVAILABILITY_VALIDATOR
      .getCacheContent();
    if (!validator.isValid(sp, id)) {
      return null;
    }
    int t1 = cast2Int(dataMap.get(FIELD_TYPE1));
    int t2 = cast2Int(dataMap.get(FIELD_TYPE2));

    if(t1 != 0) {
      if (typeSearchCensus.containsKey(t1)) {
        int tmp = typeSearchCensus.get(t1).get(-1) + 1;
        typeSearchCensus.get(t1).put(-1, tmp);
      }else {
        Map<Integer, Integer> map = new HashMap<>();
        map.put(-1, 1);
        typeSearchCensus.put(t1, map);
      }
    }
    if(t2 != 0) {
      if (typeSearchCensus.containsKey(t2)) {
        int tmp = typeSearchCensus.get(t2).get(-1) + 1;
        typeSearchCensus.get(t2).put(-1, tmp);
      }else {
        Map<Integer, Integer> map = new HashMap<>();
        map.put(-1, 1);
        typeSearchCensus.put(t2, map);
      }
    }
    return build(id).type1(t1)
                    .type2(t2);
  }

  public static SimpleSKU build(SearchParameterOrigin sp, Map<String, Object> dataMap, List<AbstractFilter> filters) {
    if (MapUtils.isEmpty(dataMap)) {
      return null;
    }
    int id = cast2Int(dataMap.get(FIELD_ID));
    AbstractValidator validator = MutableCaches.getInstance().SKU_AVAILABILITY_VALIDATOR
      .getCacheContent();
    if (!validator.isValid(sp, id)) {
      return null;
    }
    for(int i = 0; i < filters.size(); i++){
      if(!filters.get(i).isValid(dataMap, sp)){
        return null;
      }
    }

    return build(id).type1(cast2Int(dataMap.get(FIELD_TYPE1)))
                    .type2(cast2Int(dataMap.get(FIELD_TYPE2)))
                    .startTime(cast2Int(dataMap.get(FIELD_START_TIME)))
                    .endTime(cast2Int(dataMap.get(FIELD_END_TIME)));
  }

  public static SimpleSKU build(SearchParameterOrigin sp, Map<String, Object> dataMap, List<AbstractFilter> filters,
                                Map<Integer,Map<Integer,Integer>> placeSearchCensus,
                                Map<Integer,Map<Integer,Integer>> typeSearchCensus) {
    if (MapUtils.isEmpty(dataMap)) {
      return null;
    }
    int id = cast2Int(dataMap.get(FIELD_ID));
    AbstractValidator validator = MutableCaches.getInstance().SKU_AVAILABILITY_VALIDATOR
      .getCacheContent();
    if (!validator.isValid(sp, id)) {
      return null;
    }
    for(int i = 0; i < filters.size(); i++){
      if(!filters.get(i).isValid(dataMap, sp)){
        return null;
      }
    }

    int t1 = cast2Int(dataMap.get(FIELD_TYPE1));
    int t2 = cast2Int(dataMap.get(FIELD_TYPE2));

    if(t1 != 0) {
      if (typeSearchCensus.containsKey(t1)) {
        int tmp = typeSearchCensus.get(t1).get(-1) + 1;
        typeSearchCensus.get(t1).put(-1, tmp);
      }else {
        Map<Integer, Integer> map = new HashMap<>();
        map.put(-1, 1);
        typeSearchCensus.put(t1, map);
      }
    }
    if(t2 != 0) {
      if (typeSearchCensus.containsKey(t2)) {
        int tmp = typeSearchCensus.get(t2).get(-1) + 1;
        typeSearchCensus.get(t2).put(-1, tmp);
      }else {
        Map<Integer, Integer> map = new HashMap<>();
        map.put(-1, 1);
        typeSearchCensus.put(t2, map);
      }
    }

    return build(id).type1(t1)
                    .type2(t2)
                    .startTime(cast2Int(dataMap.get(FIELD_START_TIME)))
                    .endTime(cast2Int(dataMap.get(FIELD_END_TIME)));
  }

  public SimpleSKU type1(int type1) {
    setType1(type1);
    return this;
  }

  public SimpleSKU type2(int type2) {
    setType2(type2);
    return this;
  }

  @Override public int getId() {
    return id;
  }

  @Override public int getType1() {
    return type1;
  }

  public void setId(int id) {
    this.id = id;
  }

  public void setType1(int type1) {
    this.type1 = type1;
  }

  public int getType2() {
    return type2;
  }

  public void setType2(int type2) {
    this.type2 = type2;
  }

  public long getStart_time() {
    return start_time;
  }

  public long getEnd_time() {
    return end_time;
  }

  public void setEnd_time(long end_time) {
    this.end_time = end_time;
  }

  public void setStart_time(long start_time) {
    this.start_time = start_time;
  }

  public SimpleSKU startTime(long start_time){
    setStart_time(start_time);
    return this;
  }

  public SimpleSKU endTime(long end_time){
    setEnd_time(end_time);
    return this;
  }

  @Override public String toString() {
    StringBuilder sb = new StringBuilder();
    sb.append("SKU(");
    sb.append(getId());
    sb.append("@");
    sb.append(getType1());
    sb.append('.');
    sb.append(getType2());
    sb.append(')');
    return sb.toString();
  }
}
